/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "输入输出节点.h"

#include "节点/节点树.h"
#include "插座/通用插座.h"
#include "节点/插座/几何插座.h"
#include "socket_utils.h"
#include "节点数据声明.h"


static void f_get子集输出节点(C_节点树* rt, std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : rt->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

static void f_get子集输入节点(C_节点树* rt, std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : rt->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}



C_输入组节点::C_输入组节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_输入组节点, E_节点类型::e_节点Type_组输入) {
	f_setWName(u"输入组");
	m_Ctx = ctx;

	m_固定插座数量 = 固定插座数量;
	m_父节点固定插座数量 = 1;
}

C_输入组节点::~C_输入组节点() {
}

bool C_输入组节点::f_update() {

	return false;
}

C_节点基类* f_node_创建输入组节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_输入组节点(ctx);
}

C_节点基类* f_node_加载输入组节点(S_设备环境& ctx, FILE* f) {
	C_输入组节点* node = new C_输入组节点(ctx);
	return node;
}

void f_node_保存输入组节点(C_节点基类* n, FILE* f) {
	C_输入组节点* node = dynamic_cast<C_输入组节点*>(n);
}



C_输出组节点::C_输出组节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_输出组节点, E_节点类型::e_节点Type_组输出) {
	f_setWName(u"输出组");
	m_Ctx = ctx;

	m_固定插座数量 = 固定插座数量;
	m_输入节点 = nullptr;
}

C_输出组节点::~C_输出组节点() {
}

bool C_输出组节点::f_update() {
	
	return false;
}

std::string C_输出组节点::DEF_节点编译函数 {
	m_ReleaseCode = "";
	m_Code = "";

	
	auto* t = f_get父节点树();
	
	if (t->m_树类型 == E_节点树类型::e_type_函数节点树) {
		uint32 inNum = f_get输入插座数量();

		//std::string m_函数定义;
		for (uint32 i = 1; i < inNum; ++i) {
			auto* socket = f_get输入插座(i);
			//auto* 接入的插座 = socket->f_getLinkOutSocket();
			//if(!接入的插座) continue;
			m_Code += socket->f_构建变量代码(0);

			auto val = socket->f_getCode(0);
			

			if (m_输入节点) {
				uint32 outNum = m_输入节点->f_get输出插座数量();
				bool 是否输出插值引用输入插座 = false;
				for (uint32 i = 0; i < outNum; ++i) {
					auto* socket = m_输入节点->f_get输出插座(i);
			
					if (socket->f_getCode(0) == val) {
						是否输出插值引用输入插座 = true;
						break;
					}
				}
			
				if (是否输出插值引用输入插座) {
					continue;
				}
			}

			auto name = f_代码构建_节点树输出变量名称(this, i);
			if (f_代码构建_数组指针(socket)) {
				m_Code += DEF_S(f_core_array_copy);
				m_Code += "((S_Array*)" + name + ", (S_Array*)" + val + ");\n";
			}
			else {
				m_Code += name + " = " + val + ";\n";
			}
		}

		m_Code += m_ReleaseCode;
	}
	
	return m_Code;
}

C_节点基类* f_node_创建输出组节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_输出组节点(ctx);
}

C_节点基类* f_node_加载输出组节点(S_设备环境& ctx, FILE* f) {
	C_输出组节点* node = new C_输出组节点(ctx);
	return node;
}

void f_node_保存输出组节点(C_节点基类* n, FILE* f) {
	C_输出组节点* node = dynamic_cast<C_输出组节点*>(n);
}





C_插座转接节点::C_插座转接节点(S_设备环境& ctx, uint32 固定插座数量) : C_节点基类(DEF_插座转接节点, E_节点类型::e_节点Type_Reroute) {
	f_setWName(u"转接");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建引用插座_I(u"");
	DEF_创建引用插座_O(u"");
}

C_插座转接节点::~C_插座转接节点() {
}

bool C_插座转接节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
	}
	socket1 = f_get输入插座(1);
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, socket1->m_Type);

	return false;
}

std::string	C_插座转接节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto* socket1 = f_get输入插座(1);
	if (socket1->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
	}

	
	socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);
	//socket1->f_getLinkOutSocket();
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, socket1->m_Type);

	f_get输出插座(1)->f_setCode(socket1->f_getCode(0));
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

C_节点基类* f_node_创建插座转接节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_插座转接节点(ctx);
}

C_节点基类* f_node_加载插座转接节点(S_设备环境& ctx, FILE* f) {
	C_插座转接节点* node = new C_插座转接节点(ctx);
	return node;
}

void		f_node_保存插座转接节点(C_节点基类* n, FILE* f) {
	C_插座转接节点* node = dynamic_cast<C_插座转接节点*>(n);
}




C_面板框节点::C_面板框节点(S_设备环境& ctx) : C_节点基类(DEF_面板框节点, E_节点类型::e_节点Type_框) {
	f_setWName(u"框");
	m_Ctx = ctx;
}

C_面板框节点::~C_面板框节点() {
	
}

bool C_面板框节点::f_update() {
	return false;
}

void C_面板框节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_面板框节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_创建面板域节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_面板框节点(ctx);
}

C_节点基类* f_node_加载面板域节点(S_设备环境& ctx, FILE* f) {
	C_面板框节点* node = new C_面板框节点(ctx);
	return node;
}

void f_node_保存面板域节点(C_节点基类* n, FILE* f) {
	C_面板框节点* node = dynamic_cast<C_面板框节点*>(n);
}






void f_get输入节点(C_节点基类* self, std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : self->f_get子集树()->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void f_get输出节点(C_节点基类* self, std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : self->f_get子集树()->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}








C_全局变量节点::C_全局变量节点(S_设备环境& ctx) : C_节点基类(DEF_全局变量节点, E_节点类型::e_节点Type_全局) {
	f_setWName(u"全局变量");
	m_Ctx = ctx;

	m_插座可编辑 = true;
	//g_全局变量节点.insert(this);
}

C_全局变量节点::~C_全局变量节点() {

}

bool C_全局变量节点::f_update() {
	return false;
}

std::string C_全局变量节点::DEF_节点编译函数{
	return "";
}

void C_全局变量节点::f_异步解算() {
}

void C_全局变量节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		//下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_全局变量节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_计算方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_全局变量节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
}

C_节点基类* f_node_创建全局变量节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_全局变量节点(ctx);
}
C_节点基类* f_node_加载全局变量节点(S_设备环境& ctx, FILE* f) {
	C_全局变量节点* node = new C_全局变量节点(ctx);
	return node;
}
void f_node_保存全局变量节点(C_节点基类* n, FILE* f) {
	C_全局变量节点* node = static_cast<C_全局变量节点*>(n);
}




C_网格属性变量节点::C_网格属性变量节点(S_设备环境& ctx) : C_节点基类(DEF_网格属性变量节点, E_节点类型::e_节点Type_网格属性) {
	f_setWName(u"全局变量");
	m_Ctx = ctx;

	m_插座可编辑 = true;
	//g_全局变量节点.insert(this);
}

C_网格属性变量节点::~C_网格属性变量节点() {

}

bool C_网格属性变量节点::f_update() {
	uint32 num = f_get输出插座数量();

	//for (uint32 i = 1; i < num; ++i) {
	//	auto* socket = f_get输出插座(i);
	//	S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(socket);
	//	属性.m_OffsetID = i - 1;
	//	属性.m_Name = &socket->m_identifier;
	//	//属性.m_Type;
	//
	//	f_JIT_添加材质自定义网格数据布局参数(材质, &属性);
	//}
	return false;
}

std::string C_网格属性变量节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	return "";
	//std::string name = f_getName();

	uint32 num = f_get输出插座数量();
	//auto* socket1 = f_get输入插座(1);
	//auto* rt = f_getThis节点树();

	m_Code += "{\n";
	for (uint32 i = 1; i < num; ++i) {
		//if (socket1->f_isLink()) {
		//	m_Code += socket1->f_构建变量代码(0);
		//	m_Code += DEF_S(f_JIT_添加材质自定义网格数据布局参数)"(" + socket1->f_getCode(0) + ", (S_网格自定义属性*)";
		//}
		//else {
		//	m_Code += DEF_S(f_JIT_添加材质自定义网格数据布局参数)"(材质, (S_网格自定义属性*)";
		//}
		auto* socket = f_get输出插座(i);
		S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(socket);
		属性.m_OffsetID = i-1;
		属性.m_Name = &socket->m_identifier;
		//属性.m_Type;

		m_Code += DEF_S(f_JIT_添加材质自定义网格数据布局参数)"(材质, (S_网格自定义属性*)" + DEF_指针转字符串(&属性) + ");\n";

		//f_get输出插座(i)->f_setCode();
	}
	m_Code += "}\n";

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_网格属性变量节点::f_异步解算() {
}

void C_网格属性变量节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		//下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_网格属性变量节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_计算方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_网格属性变量节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
}

C_节点基类* f_node_创建网格属性变量节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_网格属性变量节点(ctx);
}
C_节点基类* f_node_加载网格属性变量节点(S_设备环境& ctx, FILE* f) {
	C_网格属性变量节点* node = new C_网格属性变量节点(ctx);
	return node;
}
void f_node_保存网格属性变量节点(C_节点基类* n, FILE* f) {
	C_网格属性变量节点* node = static_cast<C_网格属性变量节点*>(n);
}






C_成员变量节点::C_成员变量节点(S_设备环境& ctx) : C_节点基类(DEF_成员变量节点, E_节点类型::e_节点Type_类成员) {
	f_setWName(u"全局变量");
	m_Ctx = ctx;

	m_插座可编辑 = true;
	//g_全局变量节点.insert(this);
}

C_成员变量节点::~C_成员变量节点() {

}

bool C_成员变量节点::f_update() {
	return false;
}

std::string C_成员变量节点::DEF_节点编译函数{
	return "";
}

void C_成员变量节点::f_异步解算() {
}

void C_成员变量节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		//下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_成员变量节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_计算方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_成员变量节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
}

C_节点基类* f_node_创建成员变量节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_成员变量节点(ctx);
}
C_节点基类* f_node_加载成员变量节点(S_设备环境& ctx, FILE* f) {
	C_成员变量节点* node = new C_成员变量节点(ctx);
	return node;
}
void f_node_保存成员变量节点(C_节点基类* n, FILE* f) {
	C_成员变量节点* node = static_cast<C_成员变量节点*>(n);
}


